﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Modbus.Device;
using SqlSugar.Extensions;

namespace DataAcquisition
{
    internal class ModbusServices
    {
        /// <summary>串口字典
        ///  串口地址为Key
        /// </summary>
        private Dictionary<string, SerialPort> serialPortDic = new Dictionary<string, SerialPort> { };

        /// <summary>串口字典
        /// 设备编号为Key
        /// </summary>
        private Dictionary<string, SerialPort> deviceSerialPortDic = new Dictionary<string, SerialPort> { };

        /// <summary>点位字典
        /// 
        /// </summary>
        private Dictionary<string, Dictionary<string, object>> masterDic = new Dictionary<string, Dictionary<string, object>> { };

        /// <summary>界面点位字典
        /// 
        /// </summary>
        private Dictionary<string, string> frormPointDic = new Dictionary<string, string> { };


        public void Setup()
        {
            loadDeviceList();
        }

        /// <summary>设备列表
        /// 
        /// </summary>
        public void loadDeviceList()
        {
            List<Device> list = SqlHelper.Inquireable<Device>(null);

            foreach (Device item in list)
            {
                Log.Debug("开始联接端口" + item.Port);
                string deviceNumber = item.Number.ToString();
                string port_address = string.Empty; // 串口地址
                if (item.Port is not null)
                {
                    port_address = item.Port;
                }
                int baudRate = item.BaudRate;   // 波特率
                var dataBits = 8;      // 数据位
                var stopBits = StopBits.One; // 停止位
                var parity = Parity.None;    // 校验位
                SerialPort serialPort = new SerialPort(port_address, baudRate, parity, dataBits, stopBits);
                if (!serialPortDic.ContainsKey(port_address))
                {
                    try
                    {
                        serialPort.Open();
                        if (serialPort.IsOpen)
                        {
                            Log.Info(port_address + "：端口连接成功");
                            deviceSerialPortDic[item.Number.ToString()] = serialPort;
                            serialPortDic[port_address] = serialPort;
                        }
                        else
                        {
                            Log.Info(port_address + "：端口连接失败");
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(port_address + "连接异常：" + ex.Message);
                    }
                }
                else
                {
                    deviceSerialPortDic[deviceNumber] = serialPortDic[port_address];
                    Log.Info(port_address + "端口连接成功");
                }
            }

            Task.Run(() =>
            {
                loadDevicePointList();
            });
        }

        /// <summary>设备点位列表
        /// 
        /// </summary>
        public void loadDevicePointList()
        {
            List<DevicePoint> list = SqlHelper.Inquireable<DevicePoint>(null);
            foreach (DevicePoint item in list)
            {
                if (deviceSerialPortDic.ContainsKey(item.DeviceNumber.ToString()))
                {
                    Dictionary<string, Object> obj = new Dictionary<string, Object> { };
                    obj["slaveAddress"] = item.DeviceAddress;
                    obj["startAddress"] = item.Address;
                    obj["numberOfPoints"] = 1;
                    obj["rangeMin"] = item.RangeMin;
                    obj["rangeMax"] = item.RangeMax;
                    obj["signalMin"] = item.OutMin;
                    obj["signalMax"] = item.OutMax;
                    string point_name = string.Empty;
                    if (item.Name is not null)
                    {
                        point_name = item.Name;
                    }
                    obj["pointName"] = point_name;
                    obj["devicePoint"] = item;
                    SerialPort serialPort = deviceSerialPortDic[item.DeviceNumber.ToString()];
                    ModbusSerialMaster master = ModbusSerialMaster.CreateRtu(serialPort);
                    master.Transport.WriteTimeout = 1000;
                    master.Transport.ReadTimeout = 1000;
                    obj["master"] = master;
                    obj["serialPort"] = serialPort;
                    obj["deviceAddress"] = item.Address;
                    masterDic[item.Number.ToString()] = obj;
                }
                else
                {
                    string log = string.Format("【{0}】连接异常,无法读取【{1}】", item.DeviceName, item.Name);
                    Log.Error(log);
                }
            }

            Task.Run(() =>
            {
                loadFormPointList();
            });
        }

        /// <summary>界面点位列表
        /// 
        /// </summary>
        public void loadFormPointList()
        {
            List<FormPoint> list = SqlHelper.Inquireable<FormPoint>(null);
            foreach (FormPoint item in list)
            {
                string form_point_name = string.Empty;
                if (item.Name is not null)
                {
                    form_point_name = item.Name;
                }
                frormPointDic[form_point_name] = item.DevicePointNumber.ToString();
            }
        }

        public bool[]? ReadCoilsAsync(string key, int count)
        {

            if (frormPointDic.ContainsKey(key))
            {
                string pointNumber = frormPointDic[key];


                if (masterDic.ContainsKey(pointNumber))
                {
                    Dictionary<string, object> dic = masterDic[pointNumber];

                    ModbusSerialMaster master = (ModbusSerialMaster)dic["master"];

                    // 从设备地址
                    byte slaveAddress = (byte)dic["slaveAddress"].ToString().ObjToInt();

                    // 读取起始寄存器地址
                    ushort startAddress = 0;
                    string? address = dic["startAddress"].ToString();
                    if (address is not null)
                    {
                        startAddress = ushort.Parse(address);
                    }

                    // 读取寄存器数量
                    ushort numberOfPoints = 0;
                    string? points = dic["numberOfPoints"].ToString();
                    if (points is not null)
                    {
                        numberOfPoints = ushort.Parse(points);
                    }

                    if (count > 1)
                    {
                        numberOfPoints = ushort.Parse(count.ToString());
                    }
                    Task<bool[]> task = master.ReadCoilsAsync(slaveAddress, startAddress, numberOfPoints);
                    try
                    {
                        bool[] shorts = task.Result;
                        return shorts;
                    }
                    catch (Exception ex)
                    {
                        Log.Error(dic["pointName"] + " 状态异常：" + ex.Message);
                        return null;
                    }
                }
                else
                {
                    Log.Error(key + " master未创建");
                    return null;
                }
            }
            else
            {
                string log = string.Format("【{0}】点位信息不存在",key);
                Log.Error(log);
                return null;
            }
        }

        public Dictionary<string, object>? ReadInputRegistersAsync(string key, ushort count)
        {
            if (frormPointDic.ContainsKey(key))
            {
                string pointNumber = frormPointDic[key];

                if (masterDic.ContainsKey(pointNumber))
                {
                    Dictionary<string, object> dic = masterDic[pointNumber];

                    ModbusSerialMaster master = (ModbusSerialMaster)dic["master"];

                    // 从设备地址
                    byte slaveAddress = (byte)dic["slaveAddress"].ToString().ObjToInt();

                    // 读取起始寄存器地址
                    ushort startAddress = 0;
                    string? address = dic["startAddress"].ToString();
                    if (address is not null)
                    {
                        startAddress = ushort.Parse(address);
                    }

                    // 读取寄存器数量
                    if (count == 0)
                    {
                        count = 1;
                    }

                    Task<ushort[]> task = master.ReadInputRegistersAsync(slaveAddress, startAddress, count);
                    try
                    {
                        ushort[] shorts = task.Result;
                        Dictionary<string, object> back = new Dictionary<string, object>();
                        back["data"] = shorts;
                        back["devicePoint"] = dic["devicePoint"];
                        return back;
                    }
                    catch (Exception ex)
                    {
                        Log.Error(dic["pointName"] + " 温度异常：" + ex.Message);
                        return null;
                    }
                }
                else
                {
                    Log.Error(key + " master未创建");
                    return null;
                }
            }
            else
            {
                string log = string.Format("【{0}】点位信息不存在", key);
                Log.Error(log);
                return null;
            }
        }

        public bool[]? ReadInputsAsync(string key)
        {
            if (frormPointDic.ContainsKey(key))
            {
                string pointNumber = frormPointDic[key];

                if (masterDic.ContainsKey(pointNumber))
                {
                    Dictionary<string, object> dic = masterDic[pointNumber];

                    ModbusSerialMaster master = (ModbusSerialMaster)dic["master"];

                    // 从设备地址
                    byte slaveAddress = (byte)dic["slaveAddress"].ToString().ObjToInt();

                    // 读取起始寄存器地址
                    ushort startAddress = 0;
                    string? address = dic["startAddress"].ToString();
                    if (address is not null)
                    {
                        startAddress = ushort.Parse(address);
                    }

                    // 读取寄存器数量
                    ushort numberOfPoints = 0;
                    string? points = dic["numberOfPoints"].ToString();
                    if (points is not null)
                    {
                        numberOfPoints = ushort.Parse(points);
                    }

                    Task<bool[]> task = master.ReadInputsAsync(slaveAddress, startAddress, numberOfPoints);
                    try
                    {
                        bool[] shorts = task.Result;
                        return shorts;
                    }
                    catch (Exception ex)
                    {
                        Log.Error(dic["pointName"] + " 状态获取异常：" + ex.Message);
                        return null;
                    }
                }
                else
                {
                    Log.Debug(key + " master未创建");
                    return null;
                }
            }
            else
            {
                string log = string.Format("【{0}】点位信息不存在", key);
                Log.Error(log);
                return null;
            }
        }
        public Dictionary<string, object>? ReadHoldingRegistersAsync(string key)
        {
            if (frormPointDic.ContainsKey(key))
            {
                string pointNumber = frormPointDic[key];


                if (masterDic.ContainsKey(pointNumber))
                {
                    Dictionary<string, object> dic = masterDic[pointNumber];

                    ModbusSerialMaster master = (ModbusSerialMaster)dic["master"];

                    // 从设备地址
                    byte slaveAddress = (byte)dic["slaveAddress"].ToString().ObjToInt();

                    // 读取起始寄存器地址
                    ushort startAddress = 0;
                    string? address = dic["startAddress"].ToString();
                    if (address is not null)
                    {
                        startAddress = ushort.Parse(address);
                    }

                    // 读取寄存器数量
                    ushort numberOfPoints = 0;
                    string? points = dic["numberOfPoints"].ToString();
                    if (points is not null)
                    {
                        numberOfPoints = ushort.Parse(points);
                    }

                    Task<ushort[]> task = master.ReadHoldingRegistersAsync(slaveAddress, startAddress, numberOfPoints);

                    try
                    {
                        ushort[] shorts = task.Result;
                        Dictionary<string, object> back = new Dictionary<string, object>();
                        back["data"] = shorts;
                        back["devicePoint"] = dic["devicePoint"];
                        return back;
                    }
                    catch (Exception ex)
                    {
                        Log.Error(dic["pointName"] + " 结果获取异常：" + ex.Message);
                        return null;
                    }
                }
                else
                {
                    Log.Debug(key + " master未创建");
                    return null;
                }
            }
            else
            {
                string log = string.Format("【{0}】点位信息不存在", key);
                Log.Error(log);
                return null;
            }
        }
        public void WriteSingleCoil(string key, bool state)
        {
            Log.Debug("开始设置");
            if (frormPointDic.ContainsKey(key))
            {
                string pointNumber = frormPointDic[key];

                if (masterDic.ContainsKey(pointNumber))
                {
                    Dictionary<string, object> dic = masterDic[pointNumber];

                    ModbusSerialMaster master = (ModbusSerialMaster)dic["master"];

                    // 从设备地址
                    byte slaveAddress = (byte)dic["slaveAddress"].ToString().ObjToInt();

                    // 读取起始寄存器地址
                    ushort startAddress = 0;
                    string? address = dic["startAddress"].ToString();
                    if (address is not null)
                    {
                        startAddress = ushort.Parse(address);
                    }

                    // 读取寄存器数量
                    ushort numberOfPoints = 0;

                    string? points = dic["numberOfPoints"].ToString();
                    if (points is not null)
                    {
                        numberOfPoints = ushort.Parse(points);
                    }

                    try
                    {
                        master.WriteSingleCoilAsync(slaveAddress, startAddress, state);
                        
                    }
                    catch (Exception ex)
                    {
                        Log.Error(dic["pointName"] + " 设置异常：" + ex.Message);
                       
                    }
                }
                else
                {
                    string log = string.Format("【{0}】点位信息不存在", key);
                    Log.Error(log);
                }
            }
        }
    }
}
